<?php

namespace App\Repositories;

use App\Enums\Happy;
use App\Services\Tools\HelperService;
use App\Services\Tools\TimeService;
use App\Traits\GiftRank;
use App\Enums\LuckyTree;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use App\Exceptions\BasicException;
use function Clue\StreamFilter\fun;
use function foo\func;

class HappyRepository
{
    use GiftRank;

    public function getJackpotList($type, $is_next = false)
    {
        $model = $is_next ? 'ln_happy_gift_next_pool' : 'ln_happy_gift_pool';
        if ($is_next) {
            $select = [
                'a.id',
                'a.gift_id',
                'a.number',
                'b.name as gift_name',
                'b.price',
                'b.picture',
                'b.special',
            ];

        } else {
            $select = [
                'a.id',
                'a.gift_id',
                'a.number',
                'a.correction_number',
                'b.name as gift_name',
                'b.price',
                'b.picture',
                'b.special',
            ];
        }
        $list = DB::table($model.' as a')
                  ->LeftJoin('ln_gift as b', 'b.id', '=', 'a.gift_id')
                  ->select($select)
                  ->where('a.type', $type)
                  ->orderBy('b.price', 'desc')
                  ->orderBy('b.id', 'desc')
                  ->get()->map(function ($item, $key) {
                $item->quality = $this->giftRank($item->price);
                $item->key = $key + 1;

                return $item;
            });

        return $list;
    }

    /**
     * 获取游戏类型
     * @return mixed
     */
    public function getJackpotType($category = 0, $isOpen = 1)
    {
        return app('model_happy_pools_type')
            ->select(['id', 'name', 'category', 'remark', 'sort', 'is_open'])
            ->when($isOpen, function ($query, $value) {
                $query->where('is_open', $value);
            })
            ->when($category, function ($query, $value) {
                $query->where('category', $value);
            })
            ->where('id', '<>', Happy::POOL_TYPE_SUPPLY_NEXT)
            ->orderBy('sort', 'desc')
            ->orderBy('id', 'desc')
            ->get()
            ->toArray();
    }

    /**
     * 获取第一个类型
     * @param $types
     * @param $type
     * @return mixed
     */
    public function getFirstType($types, $type = 0)
    {
        $firstType = $type > 0 ? collect($types)->where('id', $type)->first() : collect($types)->first();
        !$firstType && $firstType = collect($types)->first();
        return $firstType;
    }

    /**
     * 获取最后一个类型
     * @return mixed
     */
    public function getLastType()
    {
        return app('model_happy_pools_type')->where('category', 2)->orderBy('id', 'desc')->first();
    }

    /**
     * 添加奖池类型
     * @return mixed
     */
    public function addType($data)
    {
        $data['updated_at'] = time();
        $data['created_at'] = time();
        return app('model_happy_pools_type')->create($data);
    }

    /**
     * 编辑奖池类型
     * @return mixed
     */
    public function editType($id, $data)
    {
        $data['updated_at'] = time();
        return app('model_happy_pools_type')->where('id', $id)->update($data);
    }

    /**
     * 删除奖池类型
     * @return mixed
     */
    public function delType($id)
    {
        $poolType = app('model_happy_pools_type')->where('id', $id)->first();
        if (!$poolType) {
            throw new BasicException(0,'请选择正确的奖池类型，无法删除');
        }
        if ($poolType->category == 1) {
            throw new BasicException(0,'普通奖池类型无法删除');
        }
        if ($poolType->category == 2) {
            $userPool = DB::table('ln_happy_special_user_pools')
                ->select(['type_id', 'is_current', 'user_id'])
                ->where('type_id', $id)
                ->where('is_current', 1)
                ->get();
            if ($userPool->isNotEmpty()) {
                $userIds = $userPool->pluck('user_id')->implode(',');
                throw new BasicException(0,'此特殊奖池;用户ID：'.$userIds.';正在使用中无法删除');
            }
        }
        return app('model_happy_pools_type')->where('id', $id)->delete();
    }


    //获取剩余次数
    public function getJackpotCount($type = 1, $is_next = false)
    {
        $model = $is_next ? 'model_happy_gift_next_pool' : 'model_happy_gift_pool';
        $total = app($model)->where('type', $type)->sum('number');

        return $total ?: 0;
    }

    //获取剩余总金额
    public function getJackpotTotal($type = 1, $is_next = false)
    {
        $model = $is_next ? 'ln_happy_gift_next_pool' : 'ln_happy_gift_pool';
        $total = DB::table($model.' as a')
                   ->LeftJoin('ln_gift as b', 'b.id', '=', 'a.gift_id')
                   ->where('a.type', $type)
                   ->sum(DB::raw('a.number * b.price'));

        return $total ?: 0;
    }

    /**
     * 替换奖池
     * @param $type
     * @return void
     * @throws BasicException
     */
    public function replaceJackpot($type)
    {
        $nextPrizeConfig = $this->getJackpotNext($type);
        $insertList = [];
        foreach ($nextPrizeConfig as $item) {
            $insertList[] = [
                "type"     => $type,
                "number"   => $item['number'],
                "gift_id"  => $item['gift_id'],
                "created_at" => date("Y-m-d H:i:s"),
                "remark"   => "由下期奖池覆盖替换而来",
                "weight"   => $item['weight'],
            ];
        }
        if (!empty($insertList)) {
            DB::beginTransaction();
            try {
                app('model_happy_gift_pool')->where('type', $type)->delete();
                app('model_happy_gift_pool')->insert($insertList);
            }catch (\Exception $e){
                DB::rollBack();
                throw new BasicException(0, $e->getMessage());
            }
            DB::commit();
        }
    }

    /**
     * 开启关闭奖池类型
     * @param $type
     * @return void
     * @throws BasicException
     */
    public function typeOpen($id, $openType)
    {
        // 1开启 0关闭
        return app('model_happy_pools_type')->where('id', $id)->update(['is_open' => $openType, 'updated_at' => time()]);
    }

    //获取下期奖池
    public function getJackpotNext($type)
    {
        $where = [
            ['a.is_sold', 1],
            ['a.type', $type],
            ['a.number', '>', 0]
        ];

        $list =  app('model_happy_gift_next_pool')->from('ln_happy_gift_next_pool as a')
                  ->LeftJoin('ln_gift as b', 'b.id', '=', 'a.gift_id')
                  ->select([
                      'a.gift_id',
                      'a.number',
                      'b.price',
                      'a.type',
                      'a.weight',
                  ])
                  ->where($where)
                  ->get();
        $list = empty($list)?[]:$list->toArray();
        return $list;
    }

    /**
     * 获取个人产出投入比
     * @return false|mixed|string|null
     */
    public function getRatioConfig()
    {
        $redis = app('redis');
        $key = 'happy:ratio_config';
        $ratioConfig = $redis->get($key);
        if (empty($ratioConfig)) {
            $ratioConfig = json_encode([
                'min_ratio'      => 0.8,
                'max_ratio'      => 1.2,
                'min_self_ratio' => 0.7,
                'max_self_ratio' => 1.4,
            ]);
            $redis->set($key, $ratioConfig);
        }
        return json_decode($ratioConfig, true);
    }
    /**
     * 获取特殊奖池统计数据
     */
    public function specialGiftList($params)
    {
        $redis = app('redis');

        $theory = $all = $current = [
            'times'    => 0,
            'in_coin'  => 0,
            'out_coin' => 0,
            'ratio'    => 0,
        ];
        $list = DB::table('ln_happy_gift_pool as base')
                  ->select(['base.number', 'g.price'])
                  ->leftJoin('ln_gift as g', 'base.gift_id', '=', 'g.id')
                  ->where('base.type', $params['type'])
                  ->get();
        if (!$list->isEmpty()) {
            foreach ($list as $value) {
                $theory['times'] += $value->number;
                $theory['out_coin'] += $value->number * $value->price;
            }
            $theory['in_coin'] = $theory['times'] * app('model_config')->getValue('WATERDROP_PRICE');
            $theory['ratio'] = $theory['in_coin'] == 0 ? 0 : round($theory['out_coin'] / $theory['in_coin'], 2);
        }
        // 用户中奖记录
        $current['in_coin'] = $redis->get('happy:special_incoin_total');
        $current['out_coin'] = $redis->get('happy:special_outcoin_total');
        $current['times'] = $redis->get('happy:special_times_total');
        if (empty($current['in_coin']) || empty($current['out_coin'])) {
            $recordList = DB::table('ln_happy_user_record')->selectRaw('sum(incoin_total) as in_coin,sum(outcoin_total) as out_coin,sum(number) as times')->first();
            $current['in_coin'] = $recordList->in_coin ?? 0;
            $current['out_coin'] = $recordList->out_coin ?? 0;
            $current['times'] = $recordList->times ?? 0;
            $redis->set('happy:special_incoin_total', $current['in_coin']);
            $redis->set('happy:special_outcoin_total', $current['out_coin']);
            $redis->set('happy:special_times_total', $current['times']);
        }

        if ($current['in_coin'] > 0 && $current['out_coin'] > 0) {
            $current['ratio'] = round($current['out_coin'] / $current['in_coin'], 2);

            if ($current['in_coin'] > $theory['in_coin'] && $current['out_coin'] > $theory['out_coin']) {
                $timesIncoin = ceil($current['in_coin'] / $theory['in_coin']);
                $timesOutcoin = ceil($current['out_coin'] / $theory['out_coin']);
                $times = min($timesIncoin, $timesOutcoin) - 1;
                $all['process_incoin'] = (1 - $times) * $theory['in_coin'] + $current['in_coin'];
                $all['process_outcoin'] = (1 - $times) * $theory['out_coin'] + $current['out_coin'];
                $all['ratio'] = round($all['process_outcoin'] / $all['process_incoin'], 2);
            } else {
                $all['process_incoin'] = $all['process_outcoin'] = 0;
                $all['ratio'] = round(($theory['out_coin'] + $current['out_coin']) / ($theory['in_coin'] + $current['in_coin']),
                    2);
            }
        } else {
            $all['ratio'] = $theory['in_coin'] <= 0 ? 0 : round($theory['out_coin'] / $theory['in_coin'], 2);
        }
        if (isset($params['all'])) {
            return ['all_ratio' => $all['ratio'], 'theory_ratio' => $theory['ratio']];
        }
        $key = 'happy:ratio_config';
        $ratioConfig = $redis->get($key);
        if (empty($ratioConfig)) {
            $ratioConfig = json_encode([
                'min_ratio'      => 0.8,
                'max_ratio'      => 1.2,
                'min_self_ratio' => 0.7,
                'max_self_ratio' => 1.4,
            ]);
            $redis->set($key, $ratioConfig);
        }

        $resultAll = [];
        $resultAll['in_coin'] = !empty($all['process_incoin']) ? ($theory['in_coin'].' + '.($all['process_incoin'] - $theory['in_coin'])) : ($theory['in_coin'].' + '.$current['in_coin']);
        $resultAll['out_coin'] = !empty($all['process_incoin']) ? ($theory['out_coin'].' + '.($all['process_outcoin'] - $theory['out_coin'])) : ($theory['out_coin'].' + '.$current['out_coin']);
        $resultAll['ratio'] = $all['ratio'];

        return [
            'theory'       => $theory,
            'all'          => $resultAll,
            'current'      => $current,
            'ratio_config' => json_decode($ratioConfig, true),
        ];
    }

    public function getRecord($request)
    {
        $isFlutter = $request->input('is_flutter', -1);
        $datemin = $request->input('datemin', 0);
        $datemax = $request->input('datemax', 0);
        $where = [];
        //条件查询
        if ($datemin && $datemax) {
            $datemax = $datemax." 23:59:59";
            $datemin = $datemin." 00:00:00";
            $where [] = [
                function ($query) use ($datemin, $datemax) {
                    $query->whereBetween('a.created_at', [$datemin, $datemax]);
                },
            ];
        } elseif ($datemin) {
            $datemin = $datemin." 00:00:00";
            $where[] = ['a.created_at', '>=', $datemin];
        } elseif ($datemax) {
            $datemax = $datemax." 23:59:59";
            $where[] = ['a.created_at', '<=', $datemax];
        }
        $keyword = $request->input('keyword', '');
        if ($keyword) {
            $user_ids = app('model_user_data')->where('user_code', '=', "$keyword")->orWhere('nickname', '=',
                "$keyword")->pluck('user_id');
            if ($user_ids) {
                $where[] = [
                    function ($query) use ($user_ids) {
                        $query->whereIn('a.user_id', $user_ids);
                    },
                ];
            }
        }

        $gift_id = $request->input('gift_id', 0);
        if ($gift_id > 0) {
            $where[] = ['a.gift_id', $gift_id];
        }

        if ($isFlutter == 1) {
            $where[] = ['c.price', '>=', 99999];
        } else if ($isFlutter == 0) {
            $where[] = ['c.price', '<', 99999];
        }

        $field = [
            'a.id',
            'a.user_id',
            'a.gift_id',
            'a.created_at',
            'a.number',
            'b.nickname',
            'c.name as gift_name',
            'c.price as gift_price',
            'b.user_code',
        ];
        $perPage = $request->input('perPage', 20);
        $page = $request->input('page', 1);

        if(!empty($where)){
            $list = DB::table('ln_happy_game_log as a')->select($field)
                ->leftJoin('ln_user_data as b', 'a.user_id', '=', 'b.user_id')
                ->leftJoin('ln_gift as c', 'a.gift_id', '=', 'c.id')
                ->where($where)->orderByDesc('a.id')->paginate($perPage);
            $data = $list->items();
            $page = $list->currentPage();
            $limit = $list->perPage();
            $next = $list->nextPageUrl();
            $total = $list->total();
            $request = [
                'list' => $data,
                'meta' => [
                    'page' => $page,
                    'limit' => $limit,
                    'next' => $next,
                    'total' => $total
                ]
            ];
        }else{
            $minId = app('model_happy_game_log')->min('id');
            $maxId = app('model_happy_game_log')->max('id');
            $endId = $maxId - ($page - 1) * $perPage;
            $startId = $endId - $perPage;
            $where = [['a.id', '>', $startId], ['a.id', '<=', $endId]];
            $list = DB::table('ln_happy_game_log as a')->select($field)
                ->leftJoin('ln_user_data as b', 'a.user_id', '=', 'b.user_id')
                ->leftJoin('ln_gift as c', 'a.gift_id', '=', 'c.id')
                ->where($where)
                ->orderByDesc('a.id')
                ->get()->toArray();
            $request = [
                'list' => $list,
                'meta' => [
                    'limit' => $perPage,
                    'next' => null,
                    'page' => $page,
                    'total' => $maxId - $minId + 1,
                    ]
            ];
        }
        return $request;
    }

    /**
     * @Desc:统计数据-总数据
     * @return array
     */
    public function allData()
    {
        //总
        $allTotal = $this->getData('2023-08-01 00:00:00');

        //日
        $todayRes = TimeService::today();
        $dayTotal = $this->getData(date('Y-m-d H:i:s', $todayRes[0]),date('Y-m-d H:i:s', $todayRes[1]));

        //周
        $weekRes = TimeService::week();
        $weekTotal = $this->getData(date('Y-m-d H:i:s',$weekRes[0]), date('Y-m-d H:i:s',$weekRes[1]));

        //月
        $monthRes = TimeService::month();
        $monthTotal = $this->getData(date('Y-m-d H:i:s',$monthRes[0]), date('Y-m-d H:i:s',$monthRes[1]));

        $res = [
            'all_total'   => $allTotal,
            'day_total'   => $dayTotal,
            'week_total'  => $weekTotal,
            'month_total' => $monthTotal,
        ];

        return $res;
    }

    /**
     * @Desc:
     * @param $startTime
     * @param $endTime
     * @return int[]
     * @author: shiquan
     * @Time: 2023/3/8 16:12
     */
    public function getData($startTime = '', $endTime = '')
    {
        //$where = [['game_type', '=', 3]];
        $where = [];
        if (!empty($startTime) && !empty($endTime)) {
            $where[] = ['created_at', '>=', $startTime];
            $where[] = ['created_at', '<=', $endTime];
        } elseif (!empty($startTime)){
            $where[] = ['created_at', '>=', $startTime];
        }

        $totalData = app('model_happy_user_record')
            ->where($where)
            ->selectRaw('user_id, sum(outcoin_total) as outcoin_total, sum(incoin_total) as incoin_total')
            ->groupBy('user_id')
            ->get()->toArray();

        $res = [
            'incoin_total'      => 0,/*飞屋总投入*/
            'outcoin_total'     => 0,/*飞屋总产出*/
            'profit_loss_total' => 0,/*平台盈亏*/
            'profit_number'     => 0,/*平台盈人数*/
            'loss_number'       => 0,/*平台亏人数*/
        ];
        if (!empty($totalData)){
            foreach ($totalData as $v) {
                $res['incoin_total'] += $v['incoin_total'];
                $res['outcoin_total'] += $v['outcoin_total'];
                $res['profit_loss_total'] += $v['incoin_total'] - $v['outcoin_total'];
                if ($v['incoin_total'] > $v['outcoin_total']) {
                    $res['profit_number'] += 1;
                } else {
                    $res['loss_number'] += 1;
                }
            }
        }
        $res['profit_loss_number'] = $res['profit_number'].'/'.$res['loss_number'];
        unset($res['profit_number']);
        unset($res['loss_number']);

        return $res;
    }

    /**
     * @Desc:数据统计列表信息
     * @param $params
     * @return array
     * @author: shiquan
     * @Time: 2023/3/8 16:12
     */
    public function userList($params)
    {
        //条件
        $where = [];
        //盈亏分类，并替换页码数
        if ($params['type'] == 1){
            $phase = '>0';
        } else {
            $phase = '<0';
        }
        $page = $params['page'];
        $perPage = $params['page_size'];
        //时间筛选
        if (!empty($params['start_time'])){
            $where[] = ['created_at', '>=', $params['start_time']];
        }
        if (!empty($params['end_time'])){
            $where[] = ['created_at', '<=', $params['end_time']];
        }
        //编写sql
        $model = app('model_happy_user_record')->where($where);
        $modelTotal = app('model_happy_user_record')->where($where);
        //用户code筛选
        if (isset($params['user_code']) && $params['user_code'] != -1){
            $userId = app('model_user_data')->where('user_code', 'like', "%" .$params['user_code'] . "%")->get(['user_id'])->toArray();
            $userIds = array_column($userId, 'user_id');
            $model = $model->whereIn('user_id', $userIds);
            $modelTotal = $modelTotal->whereIn('user_id', $userIds);
        }
        //执行sql
        $data = $model->groupBy('user_id')
            ->select(['user_id', DB::raw('max(created_at) as last_time'), DB::raw('sum(incoin_total) as put_data'), DB::raw('sum(outcoin_total) as get_data')])
            ->orderBy('created_at', 'desc')
            ->havingRaw('sum(incoin_total) - sum(outcoin_total)' . $phase)
            ->paginate($perPage, ['*'], '', $page)->toArray();
        //列表头部统计数据
        $totalData = $modelTotal
            ->select(['user_id', DB::raw('sum(incoin_total) as put_data'), DB::raw('sum(outcoin_total) as get_data')])
            ->havingRaw('sum(incoin_total) - sum(outcoin_total)' . $phase)
            ->groupBy('user_id')->get()->toArray();
        //拿出结果中所有的user_id，查询用户信息
        $tmpUserIds = array_column($data['data'], 'user_id');
        $userData = app('model_user_data')->whereIn('user_id', $tmpUserIds)->get(['user_id', 'user_code', 'nickname'])->toArray();
        //处理用户信息数组
        $tmpUserDataIds = array_column($userData, 'user_id');
        $tmpUserData = array_column($userData, null, 'user_id');
        //整理结果
        $list = [];
        $total = [
            'total_num' => 0,
            'total_put' => 0,
            'total_get' => 0,
            'total_phase' => 0,
        ];
        if (!empty($totalData)){
            $total = [
                'total_num' => count($totalData),
                'total_put' => array_sum(array_column($totalData, 'put_data')),
                'total_get' => array_sum(array_column($totalData, 'get_data')),
                'total_phase' => array_sum(array_column($totalData, 'put_data')) - array_sum(array_column($totalData, 'get_data'))
            ];
        }
        //循环处理结果集
        foreach ($data['data'] as $key => $value){
            //用户编号合昵称赋值
            $userCode = '';
            $nickname = '';
            if (in_array($value['user_id'], $tmpUserDataIds)){
                $userCode = $tmpUserData[$value['user_id']]['user_code'];
                $nickname =  $tmpUserData[$value['user_id']]['nickname'];
            }
            //数组赋值
            $list[] = [
                'id' => $key + 1,
                'user_code' => $userCode,
                'nickname' => $nickname,
                'incoin_total' => $value['put_data'],
                'outcoin_total' => $value['get_data'],
                'sum_profit_loss_total' => ($value['put_data'] - $value['get_data']),
                'last_drawn_time' => $value['last_time'],
            ];
        }

        return [
            'profit_loss_number' => $total['total_num'],
            'incoin_total' => $total['total_put'],
            'outcoin_total' => $total['total_get'],
            'profit_loss_total' => $total['total_phase'],
            'list' => [
                'data' => $list,
                'current_page' => $data['current_page'],
                'per_page' => $data['per_page'],
                'next_page_url' => $data['next_page_url'],
                'total' => $data['total']
            ]
        ];
    }

}
